/**
 * 网络请求封装模块
 * 支持uniapp多端兼容，包含请求拦截器、响应拦截器等功能
 */

// 导入配置
import { API_CONFIG } from './config.js'
import TokenManager from './token.js'

console.log('[request.js] Request class initializing...')

class Request {
  constructor() {
    this.baseURL = API_CONFIG.baseURL
    this.timeout = API_CONFIG.timeout
    this.header = {
      'Content-Type': 'application/json;charset=UTF-8',
      ...API_CONFIG.headers
    }
    // 令牌刷新相关
    this.isRefreshing = false
    this.failedQueue = []
  }

  /**
   * 请求拦截器
   */
  requestInterceptor(config) {
    // 添加token
    const authHeader = TokenManager.getAuthorizationHeader()
    if (authHeader) {
      config.header.Authorization = authHeader
    }

    // 显示加载提示
    if (config.loading !== false) {
      uni.showLoading({
        title: config.loadingText || '加载中...',
        mask: true
      })
    }

    console.log('请求拦截器:', config)
    return config
  }

  /**
   * 响应拦截器
   */
  responseInterceptor(response, config) {
    // 隐藏加载提示
    if (config.loading !== false) {
      uni.hideLoading()
    }

    console.log('响应拦截器:', response)

    const { data, statusCode } = response

    // HTTP状态码检查
    if (statusCode === 401) {
      // 401错误，尝试刷新令牌
      return this.handle401Error(config)
    }

    if (statusCode !== 200) {
      this.handleError(`HTTP错误: ${statusCode}`, statusCode)
      return Promise.reject(response)
    }

    // 业务状态码检查
    if (data.code !== undefined && data.code !== 200 && data.code !== 0) {
      // 业务层面的401错误也需要处理
      if (data.code === 401) {
        return this.handle401Error(config)
      }
      this.handleError(data.message || data.msg || '请求失败', data.code)
      return Promise.reject(data)
    }

    return data
  }

  /**
   * 刷新令牌
   */
  async refreshToken() {
    const refreshToken = TokenManager.getRefreshToken()
    if (!refreshToken) {
      throw new Error('没有刷新令牌')
    }

    try {
      const response = await uni.request({
        url: this.baseURL + '/app-api/member/auth/refresh-token',
        method: 'POST',
        data: { refreshToken },
        header: {
          'Content-Type': 'application/json;charset=UTF-8'
        }
      })

      if (response.statusCode === 200 && response.data.code === 0) {
        const { accessToken, refreshToken: newRefreshToken, expiresTime } = response.data.data
        
        // 更新令牌
        TokenManager.setAccessToken(accessToken)
        TokenManager.setRefreshToken(newRefreshToken)
        TokenManager.setTokenExpires(expiresTime)
        
        return accessToken
      } else {
        throw new Error(response.data.msg || '刷新令牌失败')
      }
    } catch (error) {
      console.error('刷新令牌失败:', error)
      throw error
    }
  }

  /**
   * 处理令牌刷新队列
   */
  processQueue(error, token = null) {
    this.failedQueue.forEach(({ resolve, reject }) => {
      if (error) {
        reject(error)
      } else {
        resolve(token)
      }
    })
    
    this.failedQueue = []
  }

  /**
   * 错误处理
   */
  handleError(message, code) {
    console.error('请求错误:', message, code)
    
    // 根据错误码进行不同处理
    switch (code) {
      case 401:
        // 401错误不在这里处理，由响应拦截器处理令牌刷新
        break
      case 403:
        uni.showToast({
          title: '没有权限访问',
          icon: 'none'
        })
        break
      case 404:
        uni.showToast({
          title: '请求的资源不存在',
          icon: 'none'
        })
        break
      case 500:
        uni.showToast({
          title: '服务器内部错误',
          icon: 'none'
        })
        break
      default:
        uni.showToast({
          title: message || '请求失败',
          icon: 'none'
        })
    }
  }

  /**
   * 处理401错误，尝试刷新令牌
   */
  async handle401Error(originalConfig) {
    if (this.isRefreshing) {
      // 如果正在刷新，将请求加入队列
      return new Promise((resolve, reject) => {
        this.failedQueue.push({ resolve, reject })
      }).then(token => {
        originalConfig.header.Authorization = `Bearer ${token}`
        return this.request(originalConfig)
      })
    }

    this.isRefreshing = true

    try {
      const newToken = await this.refreshToken()
      this.processQueue(null, newToken)
      
      // 重新发起原始请求
      originalConfig.header.Authorization = `Bearer ${newToken}`
      return this.request(originalConfig)
    } catch (error) {
      this.processQueue(error, null)
      
      // 刷新失败，清除令牌并跳转登录
      TokenManager.clearAll()
      uni.showToast({
        title: '登录已过期，请重新登录',
        icon: 'none'
      })
      setTimeout(() => {
        uni.reLaunch({
          url: '/pages/account/login'
        })
      }, 1500)
      
      return Promise.reject(error)
    } finally {
      this.isRefreshing = false
    }
  }

  /**
   * 通用请求方法
   */
  request(options = {}) {
    // 合并配置
    const config = {
      url: this.baseURL + options.url,
      method: options.method || 'GET',
      data: options.data || {},
      header: { ...this.header, ...options.header },
      timeout: options.timeout || this.timeout,
      loading: options.loading,
      loadingText: options.loadingText,
      ...options
    }

    // 请求拦截
    const interceptedConfig = this.requestInterceptor(config)

    // 确保POST/PUT请求的数据被正确序列化为JSON
    if (['POST', 'PUT', 'PATCH'].includes(interceptedConfig.method) && 
        interceptedConfig.header['Content-Type'] && 
        interceptedConfig.header['Content-Type'].includes('application/json')) {
      if (typeof interceptedConfig.data === 'object' && interceptedConfig.data !== null) {
        interceptedConfig.data = JSON.stringify(interceptedConfig.data)
      }
    }

    return new Promise((resolve, reject) => {
      uni.request({
        ...interceptedConfig,
        success: (response) => {
          try {
            const result = this.responseInterceptor(response, config)
            resolve(result)
          } catch (error) {
            reject(error)
          }
        },
        fail: (error) => {
          // 隐藏加载提示
          if (config.loading !== false) {
            uni.hideLoading()
          }
          
          console.error('请求失败:', error)
          this.handleError('网络请求失败，请检查网络连接')
          reject(error)
        }
      })
    })
  }

  /**
   * GET请求
   */
  get(url, params = {}, options = {}) {
    return this.request({
      url,
      method: 'GET',
      data: params,
      ...options
    })
  }

  /**
   * POST请求
   */
  post(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'POST',
      data,
      ...options
    })
  }

  /**
   * PUT请求
   */
  put(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'PUT',
      data,
      ...options
    })
  }

  /**
   * DELETE请求
   */
  delete(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'DELETE',
      data,
      ...options
    })
  }

  /**
   * 文件上传
   */
  upload(url, filePath, options = {}) {
    const config = {
      url: this.baseURL + url,
      filePath,
      name: options.name || 'file',
      formData: options.formData || {},
      header: { ...this.header, ...options.header },
      ...options
    }

    // 添加token
    const authHeader = TokenManager.getAuthorizationHeader()
    if (authHeader) {
      config.header.Authorization = authHeader
    }

    // 显示上传进度
    if (config.loading !== false) {
      uni.showLoading({
        title: '上传中...',
        mask: true
      })
    }

    return new Promise((resolve, reject) => {
      const uploadTask = uni.uploadFile({
        ...config,
        success: (response) => {
          if (config.loading !== false) {
            uni.hideLoading()
          }
          
          try {
            const data = JSON.parse(response.data)
            if (data.code === 200 || data.code === 0) {
              resolve(data)
            } else {
              this.handleError(data.message || '上传失败', data.code)
              reject(data)
            }
          } catch (error) {
            this.handleError('上传响应解析失败')
            reject(error)
          }
        },
        fail: (error) => {
          if (config.loading !== false) {
            uni.hideLoading()
          }
          this.handleError('上传失败，请检查网络连接')
          reject(error)
        }
      })

      // 监听上传进度
      if (options.onProgress) {
        uploadTask.onProgressUpdate(options.onProgress)
      }
    })
  }
}

// 创建实例
const request = new Request()

// 命名导出，避免默认导出被缓存为 undefined
export { Request, request }

export default request